﻿#include "Drawer.h"

Drawer::Drawer()
{
	mat = new Mat(1052, 1052, CV_8UC3, Scalar(255, 255, 255));
	for (int i = 0; i < blockNum * blockSize; i++)
		for (int j = 0; j < blockNum * blockSize; j++)
			codes[i][j] = 'p';
}

Drawer::~Drawer()
{
	delete mat;
}

void Drawer::setBlock(int x, int y, int content)
{
	for (int i = x; i < x + blockSize; i++)
	{
		for (int j = y; j < y + blockSize; j++)
		{
			if (codes[i][j] == 'p')
			{
				if (content == 1)
					codes[i][j] = ALI_CODE_BLACK;
				if (content == 2)
					codes[i][j] = INTERVAL_CODE;
				if (content == 3)
					codes[i][j] = TIME_CODE_BLACK;
				if (content == 4)
					codes[i][j] = TIME_CODE_WHITE;
				if (content == 5)
					codes[i][j] = CORRECTION_CODE_BLACK;
				if (content == 6)
					codes[i][j] = CORRECTION_CODE_WHITE;
				if (content == 7)
					codes[i][j] = CODE_ELEMENT;
				if (content == 8)
					codes[i][j] = PATTERN_CODE_BLACK;
				if (content == 9)
					codes[i][j] = PATTERN_CODE_WHITE;
				if (content == -1)
					codes[i][j] = DATA_BLACK;
				if (content == -2)
					codes[i][j] = DATA_WHITE;
				if (content == 255)
					codes[i][j] = ALI_CODE_WHITE;
			}
		}
	}
}
void Drawer::setBlock(int x, int y, int content,int other)
{
	for (int i = x; i < x + AlignmentBlockSize; i++)
	{
		for (int j = y; j < y + AlignmentBlockSize; j++)
		{
			if (codes[i][j] == 'p')
			{
				if (content == 1)
					codes[i][j] = ALI_CODE_BLACK;
				if (content == 2)
					codes[i][j] = INTERVAL_CODE;
				if (content == 3)
					codes[i][j] = TIME_CODE_BLACK;
				if (content == 4)
					codes[i][j] = TIME_CODE_WHITE;
				if (content == 5)
					codes[i][j] = CORRECTION_CODE_BLACK;
				if (content == 6)
					codes[i][j] = CORRECTION_CODE_WHITE;
				if (content == 7)
					codes[i][j] = CODE_ELEMENT;
				if (content == 8)
					codes[i][j] = PATTERN_CODE_BLACK;
				if (content == 9)
					codes[i][j] = PATTERN_CODE_WHITE;
				if (content == -1)
					codes[i][j] = DATA_BLACK;
				if (content == -2)
					codes[i][j] = DATA_WHITE;
				if (content == 255)
					codes[i][j] = ALI_CODE_WHITE;
			}
		}
	}
}
void Drawer::setAlignment()
{
	int x, y;
	//左上角
	x = y = 0;
	for (int i = x; i < x + AlignmentSize * AlignmentBlockSize; i += AlignmentBlockSize)
	{
		for (int j = y; j < y + AlignmentSize * AlignmentBlockSize; j += AlignmentBlockSize)
		{
			if (i == x || i == x + 6 * AlignmentBlockSize)
				setBlock(i, j, 1,1);
			else if (i == x + AlignmentBlockSize || i == x + 5 * AlignmentBlockSize)
			{
				setBlock(i, y, 1, 1);
				setBlock(i, y + 6 * AlignmentBlockSize, 1,1);
				setBlock(i, y + 1 * AlignmentBlockSize, 255,1);
				setBlock(i, y + 2 * AlignmentBlockSize, 255,1);
				setBlock(i, y + 3 * AlignmentBlockSize, 255, 1);
				setBlock(i, y + 4 * AlignmentBlockSize, 255, 1);
				setBlock(i, y + 5 * AlignmentBlockSize, 255, 1);
			}
			else if (i == x + 2 * AlignmentBlockSize || i == x + 3 * AlignmentBlockSize || i == x + 4 * AlignmentBlockSize)
			{
				setBlock(i, y, 1, 1);
				setBlock(i, y + 1 * AlignmentBlockSize, 255, 1);
				setBlock(i, y + 2 * AlignmentBlockSize, 1, 1);
				setBlock(i, y + 3 * AlignmentBlockSize, 1, 1);
				setBlock(i, y + 4 * AlignmentBlockSize, 1, 1);
				setBlock(i, y + 5 * AlignmentBlockSize, 255, 1);
				setBlock(i, y + 6 * AlignmentBlockSize, 1, 1);
			}
		}
	}
	//左下角 29*17-7*17
	x = 150 * 7 - 7 * 21;
	y = 0;
	
	for (int i = x; i < x + AlignmentSize * AlignmentBlockSize; i += AlignmentBlockSize)
	{
		for (int j = y; j < y + AlignmentSize * AlignmentBlockSize; j += AlignmentBlockSize)
		{
			if (i == x || i == x + 6 * AlignmentBlockSize)
				setBlock(i, j,1,1);
			else if (i == x + AlignmentBlockSize || i == x + 5 * AlignmentBlockSize)
			{
				setBlock(i, y, 1, 1);
				setBlock(i, y + 6 * AlignmentBlockSize, 1, 1);
				setBlock(i, y + 1 * AlignmentBlockSize, 255, 1);
				setBlock(i, y + 2 * AlignmentBlockSize, 255, 1);
				setBlock(i, y + 3 * AlignmentBlockSize, 255, 1);
				setBlock(i, y + 4 * AlignmentBlockSize, 255, 1);
				setBlock(i, y + 5 * AlignmentBlockSize, 255, 1);
			}
			else if (i == x + 2 * AlignmentBlockSize || i == x + 3 * AlignmentBlockSize || i == x + 4 * AlignmentBlockSize)
			{
				setBlock(i, y, 1, 1);
				setBlock(i, y + 1 * AlignmentBlockSize, 255, 1);
				setBlock(i, y + 2 * AlignmentBlockSize, 1, 1);
				setBlock(i, y + 3 * AlignmentBlockSize, 1, 1);
				setBlock(i, y + 4 * AlignmentBlockSize, 1, 1);
				setBlock(i, y + 5 * AlignmentBlockSize, 255, 1);
				setBlock(i, y + 6 * AlignmentBlockSize, 1, 1);
			}
		}
	}
	//右上角
	x = 0;
	y = 150 * 7 - 7 * 21;
	for (int i = x; i < x + AlignmentSize * AlignmentBlockSize; i += AlignmentBlockSize)
	{
		for (int j = y; j < y + AlignmentSize * AlignmentBlockSize; j += AlignmentBlockSize)
		{
			if (i == x || i == x + 6 * AlignmentBlockSize)
				setBlock(i, j, 1, 1);
			else if (i == x + AlignmentBlockSize || i == x + 5 * AlignmentBlockSize)
			{
				setBlock(i, y, 1, 1);
				setBlock(i, y + 6 * AlignmentBlockSize, 1, 1);
				setBlock(i, y + 1 * AlignmentBlockSize, 255, 1);
				setBlock(i, y + 2 * AlignmentBlockSize, 255, 1);
				setBlock(i, y + 3 * AlignmentBlockSize, 255, 1);
				setBlock(i, y + 4 * AlignmentBlockSize, 255, 1);
				setBlock(i, y + 5 * AlignmentBlockSize, 255, 1);
			}
			else if (i == x + 2 * AlignmentBlockSize || i == x + 3 * AlignmentBlockSize || i == x + 4 * AlignmentBlockSize)
			{
				setBlock(i, y, 1, 1);
				setBlock(i, y + 1 * AlignmentBlockSize, 255, 1);
				setBlock(i, y + 2 * AlignmentBlockSize, 1, 1);
				setBlock(i, y + 3 * AlignmentBlockSize, 1, 1);
				setBlock(i, y + 4 * AlignmentBlockSize, 1, 1);
				setBlock(i, y + 5 * AlignmentBlockSize, 255, 1);
				setBlock(i, y + 6 * AlignmentBlockSize, 1, 1);
			}
		}
	}
	/*namedWindow("t");
	imshow("t", *mat);
	waitKey(0);*/
}

void Drawer::setInterval()
{
	//左上角
	int x = 7 * blockSize;
	int y = 7 * blockSize;
	for (int i = 0; i < 8; i++)
	{
		setBlock(x, i * blockSize, 2);
		setBlock(i * blockSize, y, 2);
	}
	//左下角
	x = 21 * blockSize;
	y = 7 * blockSize;
	for (int i = 0; i < 8; i++)
	{
		setBlock(x, i * blockSize, 2);
		setBlock(21 * blockSize + i * blockSize, y, 2);
	}
	//右上角
	x = 7 * blockSize;
	y = 21 * blockSize;
	for (int i = 0; i < 8; i++)
	{
		setBlock(x, 21 * blockSize + i * blockSize, 2);
		setBlock(i * blockSize, y, 2);
	}
}

void Drawer::setBlockReverse(int x, int y)
{
	for (int i = x; i < x + blockSize; i++)
	{
		for (int j = y; j < y + blockSize; j++)
		{
			if (isupper(codes[i][j]))
				codes[i][j] = tolower(codes[i][j]);
			else if (!isupper(codes[i][j]))
				codes[i][j] = toupper(codes[i][j]);
		}
	}
}

void Drawer::setTimeBlock()
{
	//左侧
	int x = 8 * blockSize;
	int y = 6 * blockSize;
	for (int i = x; i < 21 * blockSize; i += blockSize)
	{
		int index = i / blockSize;
		//		cout << index << endl;
		if (index % 2 == 0)
		{
			setBlock(i, y, 3);
			//			cout << "black" << endl;
		}
		else
		{
			setBlock(i, y, 4);
			//			cout << "white" << endl;
		}
	}
	//左侧
	x = 6 * blockSize;
	y = 8 * blockSize;
	for (int i = y; i < 21 * blockSize; i += blockSize)
	{
		int index = i / blockSize;
		//cout << index << endl;
		if (index % 2 == 0)
		{
			setBlock(x, i, 3);
			//cout << "black" << endl;
		}
		else
		{
			setBlock(x, i, 4);
			//cout << "white" << endl;
		}
	}
}

void Drawer::drawImage()
{
	for (int i = 2; i < 1052; i++)
	{
		for (int j = 2; j < 1052; j++)
		{
			if (isupper(codes[i-2][j-2]))
			{
				mat->at<Vec3b>(i, j)[0] = 0;
				mat->at<Vec3b>(i, j)[1] = 0;
				mat->at<Vec3b>(i, j)[2] = 0;
			}
			else if (!isupper(codes[i-2][j-2]))
			{
				mat->at<Vec3b>(i, j)[0] = 255;
				mat->at<Vec3b>(i, j)[1] = 255;
				mat->at<Vec3b>(i, j)[2] = 255;
			}
		}
	}
	//上侧边框
	for (int i = 0; i < 2; i++)
	{
		for (int j = 0; j < 1052; j++)
		{
			mat->at<Vec3b>(i, j)[0] = 0;
			mat->at<Vec3b>(i, j)[1] = 0;
			mat->at<Vec3b>(i, j)[2] = 0;
		}
	}
	//左侧边框
	for (int j = 0; j < 2; j++)
	{
		for (int i = 0; i < 1052; i++)
		{
			mat->at<Vec3b>(i, j)[0] = 0;
			mat->at<Vec3b>(i, j)[1] = 0;
			mat->at<Vec3b>(i, j)[2] = 0;
		}
	}
	//下侧边框
	for (int i = 1051; i >= 1050; i--)
	{
		for (int j = 0; j < 1052; j++)
		{
			mat->at<Vec3b>(i, j)[0] = 0;
			mat->at<Vec3b>(i, j)[1] = 0;
			mat->at<Vec3b>(i, j)[2] = 0;
		}
	}
	//右侧边框
	for (int j = 1051; j >= 1050; j--)
	{
		for (int i = 0; i < 1052; i++)
		{
			mat->at<Vec3b>(i, j)[0] = 0;
			mat->at<Vec3b>(i, j)[1] = 0;
			mat->at<Vec3b>(i, j)[2] = 0;
		}
	}
	//namedWindow("t");
	//imshow("t", *mat);
	//waitKey(0);
}

void Drawer::setCorrectionCode()
{
	int center = 22;
	for (int i = 20 * blockSize; i < 25 * blockSize; i += blockSize)
	{
		if (i == 20 * blockSize || i == 24 * blockSize)
		{
			setBlock(i, 20 * blockSize, 5);
			setBlock(i, 20 * blockSize + 1 * blockSize, 5);
			setBlock(i, 20 * blockSize + 2 * blockSize, 5);
			setBlock(i, 20 * blockSize + 3 * blockSize, 5);
			setBlock(i, 20 * blockSize + 4 * blockSize, 5);
		}
		if (i == 21 * blockSize || i == 23 * blockSize)
		{
			setBlock(i, 20 * blockSize, 5);
			setBlock(i, 20 * blockSize + 1 * blockSize, 6);
			setBlock(i, 20 * blockSize + 2 * blockSize, 6);
			setBlock(i, 20 * blockSize + 3 * blockSize, 6);
			setBlock(i, 20 * blockSize + 4 * blockSize, 5);
		}
		if (i == 22 * blockSize)
		{
			setBlock(i, 20 * blockSize, 5);
			setBlock(i, 20 * blockSize + 1 * blockSize, 6);
			setBlock(i, 20 * blockSize + 2 * blockSize, 5);
			setBlock(i, 20 * blockSize + 3 * blockSize, 6);
			setBlock(i, 20 * blockSize + 4 * blockSize, 5);
		}
	}
}

void Drawer::setPattern()
{
	int x = 22 * blockSize;
	int y = 8 * blockSize;
	setBlock(x, y, 7);
	for (int i = 23 * blockSize; i < 29 * blockSize; i += blockSize)
		setBlock(i, y, 8);
	x = 0;
	y = 8 * blockSize;
	for (int i = 0; i < 9 * blockSize; i += blockSize)
		setBlock(i, y, 8);
	x = 8 * blockSize;
	y = 0;
	for (int i = 0; i < 9 * blockSize; i += blockSize)
		setBlock(x, i, 8);
	x = 8 * blockSize;
	y = 22 * blockSize;
	for (int i = 22 * blockSize; i < 29 * blockSize; i += blockSize)
		setBlock(x, i, 8);
}

void Drawer::setData(char* dataFlow)
{
	int index = 0;
	for (int i = (blockNum-1) * blockSize; i >= 0; i -= blockSize)
	{
		for (int j = (blockNum - 1) * blockSize; j >= 0; j -= blockSize)
		{
			if (codes[j][i] == 'p')
			{
				if (dataFlow[index] == 1)
				{
					setBlock(j, i, -1);
					index++;
				}
				else if(dataFlow[index]==0)
				{
					setBlock(j, i, -2);
					index++;
				}
			}
		}
	}
}

void Drawer::setMask()
{
	for (int i = 0; i < 29 * blockSize; i += blockSize)
	{
		for (int j = 0; j < 29 * blockSize; j += blockSize)
		{
			if (codes[i][j] == 'D' || codes[i][j] == 'd')
			{
				if (((i / blockSize) + (j / blockSize)) % 2 == 0)
					setBlockReverse(i, j);
			}
		}
	}
}

void Drawer::QRcode(char* data)
{
	setAlignment();
	setData(data);
	drawImage();
}

Mat* Drawer::GetMat()
{
	return mat;
}

void Drawer::showMatrix()
{
	for (int i = 0; i < 150 * blockSize; i += blockSize)
	{
		for (int j = 0; j < 150 * blockSize; j += blockSize)
		{
			cout << codes[i][j] << " ";
		}
		cout << endl;
	}
}